package com.pan.insist.exception;

import com.pan.insist.bean.BaseResponse;
import com.pan.insist.constant.CommonConstant;
import com.pan.insist.constant.HeaderConstant;
import lombok.extern.log4j.Log4j2;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.Objects;

/**
 * 全局异常处理。
 *
 * @author kaiji
 */

@Log4j2
@ControllerAdvice
public class GlobalExceptionController {

    private static final int PARAM_FAIL_CODE = CommonConstant.AjaxCode.FAIL_CODE;

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public BaseResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error(e.getMessage(), e);
        return new BaseResponse(PARAM_FAIL_CODE, Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
    }

    @ExceptionHandler(ValidationException.class)
    public BaseResponse handleValidationException(ValidationException e) {
        log.error(e.getMessage(), e);
        return new BaseResponse(PARAM_FAIL_CODE, e.getCause().getMessage());
    }

    /**
     * ConstraintViolationException
     */
    @ExceptionHandler(ConstraintViolationException .class )
    public BaseResponse handleConstraintViolationException(ConstraintViolationException e) {
        log.error(e.getMessage(), e);
        return new BaseResponse(PARAM_FAIL_CODE, e.getMessage());
    }

    /**
     * ConstraintViolationException
     */
    @ExceptionHandler(BindException.class )
    public BaseResponse handleBindException(BindException e) {
        log.error(e.getMessage(), e);
        return new BaseResponse(PARAM_FAIL_CODE, e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
    }

    /**
     * ConstraintViolationException
     */
    @ResponseBody
    @ExceptionHandler(ValidateException .class )
    public BaseResponse validateException(Exception e) {
        log.error(e.getMessage(), e);
        return new BaseResponse(PARAM_FAIL_CODE, e.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(JsonException.class)
    public BaseResponse jsonErrorHandler(Exception e) {
        if (e instanceof JsonException) {
            JsonException jsonException = (JsonException) e;
            return new BaseResponse(jsonException.getCode(), jsonException.getMessage());
        } else {
            //如果是系统的异常，比如空指针这些异常
            log.error("【系统异常】", e);
            return new BaseResponse(CommonConstant.ExceptionClazz.RESPONSE_ERROR_CODE, "服务器异常");
        }
    }


    @ExceptionHandler(value = ViewException.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) {
        ModelAndView mav = new ModelAndView();
        if (e instanceof ViewException) {
            ViewException myException = (ViewException) e;
            mav.addObject("exception", myException.getMessage());
        } else {
            log.error("【系统异常】", e);
            mav.addObject("exception", e);
        }
        String retUrl = request.getHeader(HeaderConstant.REFERER);
        mav.addObject("url", retUrl);
        mav.setViewName("error/error");
        return mav;
    }
}
